package com;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;

public class Main extends JFrame implements ActionListener, Runnable {
    public boolean isDebug = true;
    public Container container = null;// 定义容器
    JMenuItem start, exit, about;// 定义菜单按钮
    JButton landlord[] = new JButton[2];//抢地主按钮
    JButton publishCard[] = new JButton[2];//出牌按钮
    JButton allCards[] = new JButton[54];//手动摆牌时所有牌按钮
    boolean isAllCardsAllocated[] = new boolean[54];//手动摆牌时标记所有的牌是否已经分配
    JButton userButtons[] = new JButton[3]; //手动摆牌时玩家button
    JTextField playerFlag[] = new JTextField[3];//手动摆牌时玩家标记
    int[] userAllocatedCounts = new int[3]; //手动摆牌时分配的牌的数量
    JButton commitButton = new JButton("ok");//手动摆牌时提交按钮
    volatile boolean isAllocatedOk = false;          //手动摆牌是否已经完成
    int currentChosedUser = 0;              //当前摆牌的玩家
    //各个玩家摆的牌
    Map<String, List<Integer>> allocatedCardIndex = new HashMap<String, List<Integer>>();
    int dizhuFlag;//地主标志
    //当前出牌者
    int turn;
    JLabel dizhu; //地主图标
    List<Card> currentList[] = new ArrayList[3]; //  当前的出牌
    List<Card> playerList[] = new ArrayList[3]; // 定义3个玩家表
    List<Card> lordList;//地主牌
    Card card[] = new Card[56]; // 定义54张牌
    JTextField time[] = new JTextField[3]; //计时器
    Time t; //定时器（线程）
    boolean nextPlayer = false; //转换角色

    public Main() {

        Init();// 初始化
        SetMenu();// 创建菜单 按钮(抢地主，发牌,计时器)
        this.setVisible(true);
        if (!isDebug) {
            CardInit();//发牌
        }
        //直到摆牌结束才开始发牌
        if (!isAllocatedOk && isDebug) {
            while (true) {
//                try {
//                    Thread.sleep(1000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                if (isAllocatedOk) {
                    //开始发牌
                    debugCardInit();
                    break;
                }

            }
        }
        getLord(); //发完牌开始抢地主
        time[1].setVisible(true);
        //线程安全性,把非主线程的UI控制放到里面
        t = new Time(this, 10);//从10开始倒计时
        t.start();

    }

    // 抢地主
    public void getLord() {
        //System.out.println(CardType.c0.toString());
        for (int i = 0; i < 2; i++)
            landlord[i].setVisible(true);
    }

    //初始化牌（正常发牌）
    // 发牌洗牌
    public void CardInit() {

        int count = 1;
        //初始化牌
        for (int i = 1; i <= 5; i++) {
            for (int j = 1; j <= 13; j++) {
                if ((i == 5) && (j > 2))
                    break;
                else {
                    card[count] = new Card(this, i + "-" + j, false);
                    card[count].setLocation(350, 50);
                    container.add(card[count]);
                    count++;
                }
            }
        }
        //打乱顺序
        for (int i = 0; i < 100; i++) {
            Random random = new Random();
            int a = random.nextInt(54) + 1;
            int b = random.nextInt(54) + 1;
            Card k = card[a];
            card[a] = card[b];
            card[b] = k;
        }
        //开始发牌
        for (int i = 0; i < 3; i++)
            playerList[i] = new ArrayList<Card>(); //玩家牌
        lordList = new ArrayList<Card>();//地主牌三张
        int t = 0;
        for (int i = 1; i <= 54; i++) {
            if (i >= 52)//地主牌
            {
                Common.move(card[i], card[i].getLocation(), new Point(300 + (i - 52) * 80, 10));
                lordList.add(card[i]);
                continue;
            }
            switch ((t++) % 3) {
                case 0:
                    //左边玩家
                    Common.move(card[i], card[i].getLocation(), new Point(50, 60 + i * 5));
                    playerList[0].add(card[i]);
                    card[i].turnFront(); //显示正面
                    break;
                case 1:
                    //我
                    Common.move(card[i], card[i].getLocation(), new Point(180 + i * 7, 450));
                    playerList[1].add(card[i]);
                    card[i].turnFront(); //显示正面
                    break;
                case 2:
                    //右边玩家
                    Common.move(card[i], card[i].getLocation(), new Point(700, 60 + i * 5));
                    playerList[2].add(card[i]);
                    card[i].turnFront(); //显示正面
                    break;
            }

            //container.setComponentZOrder(card[i], 0);
        }
        //发完牌排序，从大到小
        for (int i = 0; i < 3; i++) {
            Common.order(playerList[i]);
            Common.rePosition(this, playerList[i], i);//重新定位
        }
        dizhu = new JLabel(new ImageIcon("images/dizhu.gif"));
        dizhu.setVisible(false);
        dizhu.setSize(40, 40);
        container.add(dizhu);

    }

    /**
     * 判断一张牌是否已经被分配（被摆牌）
     *
     * @param cardIndex
     * @param card--已经摆好的牌
     * @return
     */
    public boolean isCardAllocate(int cardIndex, List<Integer> card) {
        boolean isCardAllocate = false;
        for (int index : card) {

            if (index == cardIndex) {
                isCardAllocate = true;
            }
        }
        return isCardAllocate;
    }

    //摆牌结束后对剩余的牌发牌
    public void debugCardInit() {
        
        boolean isUserChoosedCards = true;
        if (allocatedCardIndex.get("1").isEmpty() && allocatedCardIndex.get("2").isEmpty() && allocatedCardIndex.get
                ("3").isEmpty()) {
            //没有玩家摆牌
            isUserChoosedCards = false;
        }
        List<Integer> allocatedCardIndese = new ArrayList<Integer>();
        allocatedCardIndese.addAll(allocatedCardIndex.get("1"));
        allocatedCardIndese.addAll(allocatedCardIndex.get("2"));
        allocatedCardIndese.addAll(allocatedCardIndex.get("3"));
        if (!isUserChoosedCards) {
            //玩家没有选择牌，随机发牌
            CardInit();
            return;
        }
        //玩家1摆牌选择的牌数量
        int player1Count = 1;
        //玩家2摆牌选择的牌数量
        int player2Count = 1;
        //玩家3摆牌选择的牌数量
        int player3Count = 1;
        //等待随机分配的牌（摆牌时未选中的牌）
        List<Card> waitAllocateCards = new ArrayList<Card>();
        for (int i = 1; i <= 5; i++) {
            for (int j = 1; j <= 13; j++) {
                if ((i == 5) && (j > 2))
                    break;
                else {
                    int index = 0;
                    //生成一张牌
                    Card generatedCard =  new Card(this, i + "-" + j, false);

                    generatedCard.setLocation(350, 50);
                    container.add(generatedCard);
                    

                    int color = i;
                    int number = j;
                    if (color <= 4) {
                        index = (color - 1) * 13 + number;
                    } else {
                        if (number == 1) {
                            index = 53;
                        } else {
                            index = 54;
                        }
                    }
                    //玩家1摆好的牌
                    List<Integer> player1AllocateCards = allocatedCardIndex.get("1");
                    //玩家2摆好的牌
                    List<Integer> player2AllocateCards = allocatedCardIndex.get("2");
                    //玩家3摆好的牌
                    List<Integer> player3AllocateCards = allocatedCardIndex.get("3");
                    //分为三分区间，每个区间优先摆放自己摆牌时选择的牌
                    if(isCardAllocate(index,player1AllocateCards)){
                        card[player1Count] = generatedCard;
                        player1Count += 1;
                    }else if(isCardAllocate(index,player2AllocateCards)){
                        card[player2Count+17] = generatedCard;
                        player2Count += 1;
                    }else if(isCardAllocate(index,player3AllocateCards)){
                        card[player3Count+17*2] = generatedCard;
                        player3Count += 1;
                    }else{
                        waitAllocateCards.add(generatedCard);
                    }
                    
                }
            }
        }
        //将未分配的card随机分配给三个玩家
        int waitAllocateCardSize = waitAllocateCards.size();
        List<Card> allocatedCards = new ArrayList<Card>();
        while(allocatedCards.size() < waitAllocateCardSize) {
            Random random = new Random();
            int a = random.nextInt(waitAllocateCards.size());
            Card randdomCard = waitAllocateCards.get(a);
            if(player1Count<18){
                //随机分配的牌放在各自摆牌的后边
                card[player1Count] = randdomCard;
                player1Count += 1;
            }else if(player2Count<18){
                card[player2Count+17] = randdomCard;
                player2Count += 1;
            }else if(player3Count<18){
                card[player3Count+17*2] = randdomCard;
                player3Count += 1;
            }else{
                //剩余的三张牌放到数组的最后
                if(card[52] == null){
                    card[52] = randdomCard;
                }else if(card[53] == null){
                    card[53] = randdomCard;
                }else if(card[54] == null){
                    card[54] = randdomCard;
                }
            }
            
            waitAllocateCards.remove(a);
            allocatedCards.add(randdomCard);
         
        }
        //开始发牌
        for (int i = 0; i < 3; i++)
            playerList[i] = new ArrayList<Card>(); //玩家牌
        lordList = new ArrayList<Card>();//地主牌三张
        //随机选三张地主牌
        List<Integer> tmpLordList = new ArrayList<Integer>();
        for (int index = 1; index <= 54; index++) {
            Card car = card[index];
            if (tmpLordList.size() == 3) {
                break;
            }
           
            int cardIndex = 0;

            int color = Integer.parseInt(car.name.split("-")[0]);
            int number = Integer.parseInt(car.name.split("-")[1]);
            if (color <= 4) {
                cardIndex = (color - 1) * 13 + number;
            } else {
                if (number == 1) {
                    cardIndex = 53;
                } else {
                    cardIndex = 54;
                }
            }
            
            if (!isCardAllocate(cardIndex, allocatedCardIndese)) {
                tmpLordList.add(index);
            }

        }
        //将card的后三张牌和tmpLordList下标的牌做交换
        for (int i = 0; i < 3; i++) {
            Card k = card[tmpLordList.get(i)];
            card[tmpLordList.get(i)] = card[52 + i];
            card[52 + i] = k;
        }

        int t = 0;
        for (int i = 1; i <= 54; i++) {
            if (i >= 52)//地主牌
            {
                Common.move(card[i], card[i].getLocation(), new Point(300 + (i - 52) * 80, 10));
                lordList.add(card[i]);
                continue;
            }
            if(i>17 && i<35) {
                //左边玩家
                Common.move(card[i], card[i].getLocation(), new Point(50, 60 + i * 5));
                playerList[0].add(card[i]);
                card[i].turnFront(); //显示正面
            }else if(i<=17) {

                //我
                Common.move(card[i], card[i].getLocation(), new Point(180 + i * 7, 450));
                playerList[1].add(card[i]);
                card[i].turnFront(); //显示正面
               
            } else{
                    //右边玩家
                    Common.move(card[i], card[i].getLocation(), new Point(700, 60 + i * 5));
                    playerList[2].add(card[i]);
                    card[i].turnFront(); //显示正面
                   
            }

            //container.setComponentZOrder(card[i], 0);
        }
        //发完牌排序，从大到小
        for (int i = 0; i < 3; i++) {
            Common.order(playerList[i]);
            Common.rePosition(this, playerList[i], i);//重新定位
        }
        dizhu = new JLabel(new ImageIcon("images/dizhu.gif"));
        dizhu.setVisible(false);
        dizhu.setSize(40, 40);
        container.add(dizhu);

    }

    // 初始化窗体
    public void Init() {

        this.setTitle("斗地主游戏---by 小柒,qq361106306");
        this.setSize(1200, 620);
        setResizable(false);
        setLocationRelativeTo(getOwner()); // 屏幕居中
        container = this.getContentPane();
        container.setLayout(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        container.setBackground(new Color(0, 112, 26)); // 背景为绿色

    }

    // 创建菜单 功能按钮
    public void SetMenu() {
        JMenuBar jMenuBar = new JMenuBar();
        JMenu game = new JMenu("游戏");
        JMenu help = new JMenu("帮助");

        start = new JMenuItem("新游戏");
        exit = new JMenuItem("退出");
        about = new JMenuItem("关于");

        start.addActionListener(this);
        exit.addActionListener(this);
        about.addActionListener(this);

        game.add(start);
        game.add(exit);
        help.add(about);

        jMenuBar.add(game);
        jMenuBar.add(help);
        this.setJMenuBar(jMenuBar);

        landlord[0] = new JButton("抢地主");
        landlord[1] = new JButton("不     抢");
        publishCard[0] = new JButton("出牌");
        publishCard[1] = new JButton("不要");
        for (int i = 0; i < 2; i++) {
            //830, 620
            publishCard[i].setBounds(320 + i * 100, 400, 60, 20);
            landlord[i].setBounds(320 + i * 100, 400, 75, 20);
            container.add(landlord[i]);
            landlord[i].addActionListener(this);
            landlord[i].setVisible(false);
            container.add(publishCard[i]);
            publishCard[i].setVisible(false);
            publishCard[i].addActionListener(this);
        }

        for (int i = 0; i < 3; i++) {
            time[i] = new JTextField("倒计时:");
            time[i].setVisible(false);
            container.add(time[i]);
        }
        time[0].setBounds(140, 230, 60, 20);
        time[1].setBounds(374, 360, 60, 20);
        time[2].setBounds(620, 230, 60, 20);
        //手动摆牌按钮
        if (isDebug) {
            for (int i = 0; i < allCards.length; i++) {
                int index = i + 1;
                String value = "";
                if (index == 53) {
                    value = "小";
                } else if (index == 54) {
                    value = "大";
                } else {
                    int yu = index % 13;
                    if (yu == 1) {
                        value = "A";
                    } else if (yu == 11) {
                        value = "J";
                    } else if (yu == 12) {
                        value = "Q";
                    } else if (yu == 0) {
                        value = "K";
                    } else {
                        value = "" + yu;
                    }
                }
                //830, 620

                int row = 0;
                int shang = index / 13;
                int yu = index % 13;
                if (yu == 0) {
                    row = shang;
                } else {
                    row = shang + 1;
                }

                if (yu == 0) {
                    yu = 13;
                }
                allCards[i] = new JButton(value);
                allCards[i].setToolTipText(value + "_" + index);
                allCards[i].setBounds(70 + yu * 50, 100 + row * 20, 50, 20);
                allCards[i].setVisible(true);
                allCards[i].addActionListener(this);
                container.add(allCards[i]);
            }
            for (int i = 0; i < 3; i++) {
                userButtons[i] = new JButton();
                int currenUser = i + 1;
                userButtons[i].setToolTipText(currenUser + "");
                userButtons[i].setBounds(10, 100 + (6 + i) * 20, 50, 20);
                userButtons[i].setVisible(true);
                userButtons[i].addActionListener(this);
                container.add(userButtons[i]);


                playerFlag[i] = new JTextField("玩家"+currenUser);
                playerFlag[i].setBounds(60, 100 + (6 + i) * 20, 50, 20);
                playerFlag[i].setVisible(true);
                playerFlag[i].addActionListener(this);
                container.add(playerFlag[i]);
            }
            commitButton.setBounds(70 + 7 * 50, 100 + 9 * 20, 50, 20);
            commitButton.setVisible(true);
            commitButton.addActionListener(this);
            container.add(commitButton);

        }

        for (int i = 0; i < 3; i++) {
            currentList[i] = new ArrayList<Card>();
            int user = i + 1;
            allocatedCardIndex.put("" + user, new ArrayList<Integer>());
        }


    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        if (e.getSource() == exit) {
            this.dispose();
        }
        if (e.getSource() == about) {
            JOptionPane.showMessageDialog(this, "QQ361106306,小柒");
        }
        if (e.getSource() == start) {
            // this.restart();
        }
        //摆牌结束后需要对摆牌组件设置为disable不可见
        if (e.getSource() == commitButton) {
            isAllocatedOk = true;
            //debug组件设置disable
            for (JButton cardButton : allCards) {
                cardButton.setVisible(false);
                container.remove(cardButton);
            }
            for (JButton button : userButtons) {
                button.setVisible(false);
                container.remove(button);
            }
            for(JTextField button : playerFlag){
                button.setVisible(false);
                container.remove(button);
            }

            commitButton.setVisible(false);
            container.remove(commitButton);

            
        }
        //玩家标志button
        for (int i = 0; i < userButtons.length; i++) {
            if (e.getSource() == userButtons[i]) {
                userButtons[i].setText(".");
                for (int j = 0; j < userButtons.length; j++) {
                    if (j != i) {
                        userButtons[j].setText("");
                    }
                }
                currentChosedUser = Integer.parseInt(userButtons[i].getToolTipText());
                break;
            }
        }


        for (int i = 0; i < allCards.length; i++) {
            if (e.getSource() == allCards[i]) {
                if (currentChosedUser == 0) {
                    break;
                }
                allCards[i].setVisible(false);
                //container.remove(allCards[0]);
                int index = Integer.parseInt(allCards[i].getToolTipText().split("_")[1]);
                int row = 0;
                int shang = index / 13;
                int yu = index % 13;
                if (yu == 0) {
                    row = shang;
                } else {
                    row = shang + 1;
                }

                if (yu == 0) {
                    yu = 13;
                }

                if (isAllCardsAllocated[i] == true) {
                    if (currentChosedUser > 0 && currentChosedUser == ((allCards[i].getY() - 100) / 20 - 5)) {
                        userAllocatedCounts[currentChosedUser - 1] -= 1;
                        for (int j = 0; j < isAllCardsAllocated.length; j++) {
                            if (isAllCardsAllocated[j] && currentChosedUser == ((allCards[j].getY() - 100) / 20 - 5) &&
                                    allCards[j].getX() > allCards[i].getX()) {
                                allCards[j].setVisible(false);
                                allCards[j].setVisible(true);
                                container.add(allCards[j]);
                                allCards[j].setBounds(allCards[j].getX() - 50, allCards[j].getY(), 50, 20);

                            }
                        }
                        isAllCardsAllocated[i] = !isAllCardsAllocated[i];
                        allCards[i].setBounds(70 + yu * 50, 100 + row * 20, 50, 20);
                        List<Integer> userCards = allocatedCardIndex.get("" + currentChosedUser);
                        int removeIndex = 0;
                        for (int q = 0; q < userCards.size(); q++) {
                            if (Integer.parseInt(allCards[i].getToolTipText().split("_")[1]) == userCards.get(q)) {
                                removeIndex = q;
                            }
                        }
                        userCards.remove(removeIndex);
                    }

                } else {
                    if (currentChosedUser > 0) {
                        List<Integer> userCards = allocatedCardIndex.get("" + currentChosedUser);
                        if (userCards.size() < 17) {
                            isAllCardsAllocated[i] = !isAllCardsAllocated[i];
                            userAllocatedCounts[currentChosedUser - 1] += 1;
                            allCards[i].setBounds(70 + userAllocatedCounts[currentChosedUser - 1] * 50, 100 +
                                            (5 + currentChosedUser) * 20, 50,
                                    20);

                            userCards.add(Integer.parseInt(allCards[i].getToolTipText().split("_")[1]));
                        }

                    }
                }

                allCards[i].setVisible(true);
                container.add(allCards[i]);
                break;
            }

        }


        if (e.getSource() == landlord[0]) {
            time[1].setText("抢地主");
            t.isRun = false; //时钟终结
        }
        if (e.getSource() == landlord[1]) {
            time[1].setText("不抢");
            t.isRun = false; //时钟终结
        }
        //如果是不要
        if (e.getSource() == publishCard[1]) {
            this.nextPlayer = true;
            currentList[1].clear();
            time[1].setText("不要");
        }
        //如果是出牌按钮
        if (e.getSource() == publishCard[0]) {
            List<Card> c = new ArrayList<Card>();
            //点选出牌
            for (int i = 0; i < playerList[1].size(); i++) {
                Card card = playerList[1].get(i);
                if (card.clicked) {
                    c.add(card);
                }
            }
            int flag = 0;

            //如果我主动出牌
            if (time[0].getText().equals("不要") && time[2].getText().equals("不要")) {
                if (Common.jugdeType(c) != CardType.c0)
                    flag = 1;//表示可以出牌
            }//如果我跟牌
            else {
                flag = Common.checkCards(c, currentList, this);
            }
            //判断是否符合出牌
            if (flag == 1) {
                currentList[1] = c;
                playerList[1].removeAll(currentList[1]);//移除走的牌
                //定位出牌
                Point point = new Point();
                point.x = (770 / 2) - (currentList[1].size() + 1) * 15 / 2;
                ;
                point.y = 300;
                for (int i = 0, len = currentList[1].size(); i < len; i++) {
                    Card card = currentList[1].get(i);
                    Common.move(card, card.getLocation(), point);
                    point.x += 15;
                }
                //抽完牌后重新整理牌
                Common.rePosition(this, playerList[1], 1);
                time[1].setVisible(false);
                this.nextPlayer = true;
            }
            //不能出牌的话则出牌按钮点不动
        }
    }

    public static void main(String args[]) {

        new Thread(new Main()).start();

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

    }

}

